package com.summer.filesync.serialization;

import com.summer.filesync.util.Logger;
import java.io.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/** 序列化管理器 提供对象序列化和反序列化功能 */
public class SerializationManager {

  private static final Logger logger = Logger.getLogger(SerializationManager.class);

  /** 序列化对象到字节数组 */
  public static byte[] serialize(Object obj) throws IOException {
    if (obj == null) {
      return null;
    }

    try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
        GZIPOutputStream gzos = new GZIPOutputStream(baos);
        ObjectOutputStream oos = new ObjectOutputStream(gzos)) {

      oos.writeObject(obj);
      oos.flush();
      gzos.finish();

      byte[] result = baos.toByteArray();
      logger.debug(
          "Serialized object of type "
              + obj.getClass().getSimpleName()
              + " to "
              + result.length
              + " bytes");
      return result;

    } catch (IOException e) {
      logger.error("Failed to serialize object of type " + obj.getClass().getSimpleName(), e);
      throw e;
    }
  }

  /** 从字节数组反序列化对象 */
  public static <T> T deserialize(byte[] data, Class<T> clazz)
      throws IOException, ClassNotFoundException {
    if (data == null || data.length == 0) {
      return null;
    }

    try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
        GZIPInputStream gzis = new GZIPInputStream(bais);
        ObjectInputStream ois = new ObjectInputStream(gzis)) {

      Object obj = ois.readObject();
      logger.debug(
          "Deserialized object of type "
              + clazz.getSimpleName()
              + " from "
              + data.length
              + " bytes");

      return clazz.cast(obj);

    } catch (IOException | ClassNotFoundException e) {
      logger.error("Failed to deserialize object of type " + clazz.getSimpleName(), e);
      throw e;
    }
  }

  /** 序列化对象到文件 */
  public static void serializeToFile(Object obj, String filePath) throws IOException {
    if (obj == null) {
      throw new IllegalArgumentException("Object to serialize cannot be null");
    }

    File file = new File(filePath);
    File parentDir = file.getParentFile();
    if (parentDir != null && !parentDir.exists()) {
      if (!parentDir.mkdirs()) {
        throw new IOException("Failed to create directory: " + parentDir.getPath());
      }
    }

    try (FileOutputStream fos = new FileOutputStream(file);
        GZIPOutputStream gzos = new GZIPOutputStream(fos);
        ObjectOutputStream oos = new ObjectOutputStream(gzos)) {

      oos.writeObject(obj);
      oos.flush();
      gzos.finish();

      logger.info("Serialized object to file: " + filePath);

    } catch (IOException e) {
      logger.error("Failed to serialize object to file: " + filePath, e);
      throw e;
    }
  }

  /** 从文件反序列化对象 */
  public static <T> T deserializeFromFile(String filePath, Class<T> clazz)
      throws IOException, ClassNotFoundException {
    File file = new File(filePath);
    if (!file.exists()) {
      throw new FileNotFoundException("File not found: " + filePath);
    }

    try (FileInputStream fis = new FileInputStream(file);
        GZIPInputStream gzis = new GZIPInputStream(fis);
        ObjectInputStream ois = new ObjectInputStream(gzis)) {

      Object obj = ois.readObject();
      logger.info("Deserialized object from file: " + filePath);

      return clazz.cast(obj);

    } catch (IOException | ClassNotFoundException e) {
      logger.error("Failed to deserialize object from file: " + filePath, e);
      throw e;
    }
  }

  /** 不压缩的序列化 */
  public static byte[] serializeWithoutCompression(Object obj) throws IOException {
    if (obj == null) {
      return null;
    }

    try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos)) {

      oos.writeObject(obj);
      oos.flush();

      byte[] result = baos.toByteArray();
      logger.debug("Serialized object without compression to " + result.length + " bytes");
      return result;

    } catch (IOException e) {
      logger.error("Failed to serialize object without compression", e);
      throw e;
    }
  }

  /** 不压缩的反序列化 */
  public static <T> T deserializeWithoutCompression(byte[] data, Class<T> clazz)
      throws IOException, ClassNotFoundException {
    if (data == null || data.length == 0) {
      return null;
    }

    try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
        ObjectInputStream ois = new ObjectInputStream(bais)) {

      Object obj = ois.readObject();
      logger.debug("Deserialized object without compression from " + data.length + " bytes");

      return clazz.cast(obj);

    } catch (IOException | ClassNotFoundException e) {
      logger.error("Failed to deserialize object without compression", e);
      throw e;
    }
  }

  /** 检查对象是否可序列化 */
  public static boolean isSerializable(Object obj) {
    return obj instanceof Serializable;
  }

  /** 获取序列化后的大小（不实际序列化） */
  public static long getSerializedSize(Object obj) {
    if (obj == null) {
      return 0;
    }

    try {
      byte[] data = serialize(obj);
      return data != null ? data.length : 0;
    } catch (IOException e) {
      logger.warn("Failed to calculate serialized size for object", e);
      return -1;
    }
  }
}
